package collector

import (
	"context"
	"github.com/go-kit/kit/log"
	"github.com/go-redis/redis/v8"
	"github.com/prometheus/client_golang/prometheus"
)

// 性能指标
// latency 响应时间
// instantaneous_ops_per_sec 平均每秒处理请求总数
// hi_rate 缓存命中率

const (
	// Subsystem.
	performance = "performance"
	//
	latency       = "latency"
	instOpsPerSec = "instantaneous_ops_per_sec"
	hiRate        = "hi_rate"
)

// Metric descriptors.
var (
	latencyDesc = prometheus.NewDesc(
		prometheus.BuildFQName(namespace, performance, latency),
		"请求响应时间",
		[]string{}, nil,
	)
	instOpsPerSecDesc = prometheus.NewDesc(
		prometheus.BuildFQName(namespace, performance, instOpsPerSec),
		"每秒处理的命令数",
		[]string{}, nil,
	)
	hiRateDesc = prometheus.NewDesc(
		prometheus.BuildFQName(namespace, performance, hiRate),
		"缓存命中率",
		[]string{}, nil,
	)
)

// ScrapePerformance collects from performance.
type ScrapePerformance struct{}

// Name of the Scraper. Should be unique.
func (ScrapePerformance) Name() string {
	return performance
}

// Help describes the role of the Scraper.
func (ScrapePerformance) Help() string {
	return "Collect the current size of all registered binlog files"
}

// Version of Redis from which scraper is available.
func (ScrapePerformance) Version() float64 {
	return 4.0
}

// Scrape collects data from redis connection and sends it over channel as prometheus metric.
func (ScrapePerformance) Scrape(ctx context.Context, client *redis.Client, ch chan<- prometheus.Metric, logger log.Logger) error {

	var lat float64 = 0

	data, err := infos(client, "stats")
	if err != nil {
		return err
	}

	iop := valueOf(data, instOpsPerSec)

	// 服务器处理的命令总数
	hit := valueOf(data, "keyspace_hits")
	// 服务器处理的命令总数
	total := valueOf(data, "total_commands_processed")
	// 命中率
	var hiRate = 0.0
	if hit != 0 {
		hiRate = hit / total
	}

	ch <- prometheus.MustNewConstMetric(
		latencyDesc, prometheus.GaugeValue, lat,
	)
	ch <- prometheus.MustNewConstMetric(
		instOpsPerSecDesc, prometheus.GaugeValue, iop,
	)

	ch <- prometheus.MustNewConstMetric(
		hiRateDesc, prometheus.GaugeValue, hiRate,
	)

	return nil
}

// check interface
var _ Scraper = ScrapePerformance{}
